import {
  ROOM_STATUS,
  PLAYER_STATUS,
  roomStatusToString,
  playerStatusToString
} from "../../STATUS";
import rule from "../../core/min_rule";
import Card, { CardList, CARD_LIST } from "../../core/Card";
import render_player, {
  init_loader as render_player_init_loader
} from "./render_player";
import { vueStageComponentWrapper } from "../../core/componentGenerator";
export default vueStageComponentWrapper("gaming", {
  data() {
    return {
      ROOM_STATUS,
      PLAYER_STATUS,
      img_url: {},
      card_list: [],
      top_card_list: [],
      mid_card_list: [],
      btm_card_list: [],
      mul_select_from: null,
      mul_select_to: null,
      is_special: false,
      special_info: {},

      com_two_list: [],
      com_two_pair_list: [],
      com_three_list: [],
      com_straight_list: [],
      com_flush_list: [],
      com_full_house_list: [],
      com_four_list: [],
      com_straight_flush_list: [],

      // 自定义牌组
      is_change_card_list: false,
      CARD_LIST,
      selected_custom_card_list: []
    };
  },
  resources: {
    gaming_bg: "game/Game_UI_01.png",
    done_btn: "game/Finish_01.png",
    done_hover_btn: "game/Finish_02.png",
    clear_btn: "game/retry_01.png",
    clear_hover_btn: "game/retry_02.png",
    cards_mask_top: "game/Card_UI_03.png",
    cards_mask_mid: "game/Card_UI_02.png",
    cards_mask_btm: "game/Card_UI_01.png",

    auto_two: "game/duizi_00.png",
    auto_two_pair: "game/liangdui_01.png",
    auto_three: "game/santiao_01.png",
    auto_straight: "game/shunzi_01.png",
    auto_flush: "game/tonghua_01.png",
    auto_full_house: "game/hulu_01.png",
    auto_four: "game/zhadan_01.png",
    auto_straight_flush: "game/同花顺.png",
    auto_special: "game/特殊牌(1).png",
    RPIL: render_player_init_loader,
    CSIL: PIXI.CardSpirte.init_loader
  },
  next_stages: ["wait-end-game"],
  created() {
    // 监测特殊牌
    this.$watch(
      "player.card_list",
      card_name_list => {
        const card_list = card_name_list.map(card_name =>
          Card.getIns(card_name)
        );
        CardList.sort_cards(card_list);
        card_list.forEach(card => card.reset());
        this.card_list = card_list;
        // this.card_list.sort_cards();
        this.is_change_card_list = false;
        // 检测是否可以报道
        socket.emit("is-special-card-list", card_name_list);
        socket.once("special-card-list-res", res_info => {
          console.log("special-card-list-res", res_info);
          if (res_info && res_info.type) {
            this.is_special = true;
            this.special_info = res_info;
          } else {
            this.is_special = false;
            this.special_info = null;
          }
        });
      },
      {
        immediate: true
      }
    );
    const com_list_map = new Map();
    this.$watch(
      "card_list",
      card_list => {
        // 监测基本的智能牌组
        [
          "two",
          "two_pair",
          "three",
          "straight",
          "flush",
          "full_house",
          "four",
          "straight_flush"
        ].forEach(type => {
          const useable_card_list = card_list.filter(card => !card.is_used);
          const useable_card_list_val = useable_card_list.join("|");
          const com_key = "com_" + type + "_list";
          if (com_list_map.get(com_key) === useable_card_list_val) {
            return;
          }
          com_list_map.set(com_key, useable_card_list_val);
          const com_list = rule["check_" + type](useable_card_list);
          this[com_key] = com_list;
        });
      },
      {
        immediate: true,
        deep: true
      }
    );

    // PIXI
    const { unwatchers, app, loader } = this;

    loader.onError.add(err => console.error(err));
    this.draw_app = async () => {
      console.log("DRAW GAMING");
      const loader = this.loader;
      if (!loader) {
        // maybe run on after destroyed
        return;
      }
      this.clearWatch();
      const resources = loader.resources;
      app.stage.destroy();
      const stage = (app.stage = new PIXI.Container());
      const { width, height } = app.renderer;
      const bg = new PIXI.Sprite(resources.bg.texture);
      bg.width = width;
      bg.height = height;
      stage.addChild(bg);

      const { avatar_box_bounds } = await render_player.call(this, {
        app,
        stage,
        resources,
        width,
        height,
        unwatchers
      });

      // 摆牌面板
      const $gaming_panel = new PIXI.Container();
      stage.addChild($gaming_panel);
      const $gaming_bg = new PIXI.Sprite(resources.gaming_bg.texture);
      $gaming_bg.maxWidthHeight(width * 0.7, height * 0.5);
      $gaming_bg.x = width / 2 - $gaming_bg.width / 2;
      $gaming_bg.y = $gaming_bg.height * 0.15;
      $gaming_panel.addChild($gaming_bg);
      // 提交按钮
      const $done_btn = new PIXI.Sprite(resources.done_btn.texture);
      $done_btn.hoverSprite(resources.done_hover_btn.texture);
      $done_btn.bindTap(this.submitRes.bind(this));
      $done_btn.maxWidth(avatar_box_bounds.width * 1.5);
      let _is_done_btn_to_right;
      if (width - $gaming_bg.width > avatar_box_bounds.width * 4) {
        // 把按钮放置倒右边
        _is_done_btn_to_right = true;
      } else if (width - $gaming_bg.width > avatar_box_bounds.width * 2) {
        // 把按钮放置倒右边并且改变背景面板的坐标
        _is_done_btn_to_right = true;
        $gaming_bg.x = width - $gaming_bg.width - avatar_box_bounds.width * 2;
      } else {
        _is_done_btn_to_right = false;
      }
      const gaming_bg_bounds = $gaming_bg.getBounds();
      if (_is_done_btn_to_right) {
        $done_btn.x = gaming_bg_bounds.right + avatar_box_bounds.width * 0.2;
        $done_btn.y = gaming_bg_bounds.bottom - $done_btn.height;
      } else {
        $done_btn.x = width / 2 - $done_btn.width / 2;
        $done_btn.y = gaming_bg_bounds.bottom + $done_btn.height * 0.2;
      }
      $gaming_panel.addChild($done_btn);
      /* 重置按钮，与遮罩面板 */
      // 头，中，尾
      ["top", "mid", "btm"].forEach((key, i) => {
        const $clear_card_list = new PIXI.Sprite(resources.clear_btn.texture);
        $clear_card_list.hoverSprite(resources.clear_hover_btn.texture);
        $clear_card_list.maxWidth(gaming_bg_bounds.width * 0.06);
        $clear_card_list.x =
          gaming_bg_bounds.right - gaming_bg_bounds.width * 0.12;
        if (i === 0) {
          // $clear_card_list.x = gaming_bg_bounds.right-gaming_bg_bounds.width*0.25;
          $clear_card_list.y =
            gaming_bg_bounds.top + gaming_bg_bounds.height * 0.1;
        } else if (i === 1) {
          // $clear_card_list.x = gaming_bg_bounds.right-gaming_bg_bounds.width*0.15;
          $clear_card_list.y =
            gaming_bg_bounds.top + gaming_bg_bounds.height * 0.31;
        } else {
          $clear_card_list.y =
            gaming_bg_bounds.top + gaming_bg_bounds.height * 0.6;
        }
        $clear_card_list.bindTap(() => {
          this.removeFromResCards(key + "_card_list");
        });
        $gaming_panel.addChild($clear_card_list);
        unwatchers[unwatchers.length] = this.$watch(
          key + "_card_list.length",
          has_len => {
            $clear_card_list.visible = !!has_len;
          },
          {
            immediate: true
          }
        );

        const $cards_mask = new PIXI.Sprite(
          resources["cards_mask_" + key].texture
        );
        if (i === 0) {
          $cards_mask.maxWidth(gaming_bg_bounds.width * 0.376);
          $cards_mask.x =
            gaming_bg_bounds.left + gaming_bg_bounds.width * 0.325;
          $cards_mask.y = gaming_bg_bounds.top + gaming_bg_bounds.height * 0.06;
        } else if (i === 1) {
          $cards_mask.maxWidth(gaming_bg_bounds.width * 0.578);
          $cards_mask.x =
            gaming_bg_bounds.left + gaming_bg_bounds.width * 0.224;
          $cards_mask.y = gaming_bg_bounds.top + gaming_bg_bounds.height * 0.29;
        } else {
          $cards_mask.maxWidth(gaming_bg_bounds.width * 0.64);
          $cards_mask.x =
            gaming_bg_bounds.left + gaming_bg_bounds.width * 0.192;
          $cards_mask.y =
            gaming_bg_bounds.top + gaming_bg_bounds.height * 0.505;
        }
        $gaming_panel.addChild($cards_mask);
        $cards_mask.bindTap(() => {
          this.addSelectedCardsToRes(key + "_card_list", key === "top" ? 3 : 5);
        });
        unwatchers[unwatchers.length] = this.$watch(
          key + "_card_list",
          card_list => {
            $cards_mask.children.slice().forEach(child => child.destroy());
            card_list.forEach((card, i) => {
              const $card = new PIXI.CardSpirte(card, resources);
              if (key === "top") {
                $card.x = $card.width * (i * 0.58 - 0.02);
              } else if (key === "mid") {
                $card.x = $card.width * (i * 0.577 - 0.03);
              } else {
                $card.x = $card.width * (i * 0.68 - 0.03);
              }
              $cards_mask.addChild($card);
            });
            // cards.
          },
          {
            immediate: true
          }
        );
      });

      unwatchers[unwatchers.length] = this.$watch(
        "player.status",
        status => {
          $gaming_panel.visible = true;
          if (status === PLAYER_STATUS.BEFORE_SUBMIT) {
            $gaming_panel;
          } else {
            $ready_button.visible = false;
          }
        },
        { immediate: true }
      );

      // 底部智能选牌部分
      const $auto_btm_list = new PIXI.Container();
      stage.addChild($auto_btm_list);
      const auto_btm_list = [
        "two",
        "two_pair",
        "three",
        "straight",
        "flush",
        "full_house",
        "four",
        "straight_flush",
        "special"
      ];
      let acc_width = 0;
      const btm_height = width * 0.0562;
      auto_btm_list.forEach((type, i) => {
        const $btm = new PIXI.Sprite(resources["auto_" + type].texture);
        $btm.maxHeight(btm_height);
        $btm.x = acc_width - btm_height / 2 * i;
        acc_width += $btm.width;
        $auto_btm_list.addChild($btm);

        if (type === "special") {
          unwatchers[
            unwatchers.length
          ] = this.$watch(
            "is_special",
            is_special => {
              $btm.tint = is_special ? 0xffffff : 0x999999;
            },
            {
              immediate: true
            }
          );
          $btm.bindTap(() => {
            this.submitResWithSpecial();
          });
        } else {
          let cards_list;
          let _p = 0;
          unwatchers[unwatchers.length] = this.$watch(
            "com_" + type + "_list",
            res_list => {
              cards_list = res_list;
              _p = 0;
              if (res_list.length) {
                $btm.tint = 0xffffff;
              } else {
                $btm.tint = 0x999999;
              }
            },
            {
              immediate: true
            }
          );
          $btm.bindTap(() => {
            _p = _p % cards_list.length;
            const cards = cards_list[_p];
            if (cards) {
              this.card_list.forEach(card => this.selectCard(card, false));
              cards.forEach(card => this.selectCard(card, true));
              _p += 1;
            }
          });
        }
      });
      $auto_btm_list.y = height - $auto_btm_list.height;

      // 渲染手牌
      const $hand_card_list = new PIXI.Container();
      $hand_card_list.interactive = true;
      $hand_card_list.on("pointerupoutside", () => {
        this.endSelectCard();
      });
      let hand_card_list_bounds;
      $hand_card_list.on("pointermove", e => {
        const touch_point = e.data.global;
        if (
          !hand_card_list_bounds ||
          !hand_card_list_bounds.contains(touch_point.x, touch_point.y)
        ) {
          return;
        }
        // 倒序，牌的坐标是覆盖的
        for (let i = card_list_bounds.length - 1; i >= 0; i -= 1) {
          const { card_index, bounds } = card_list_bounds[i];
          if (bounds.contains(touch_point.x, touch_point.y)) {
            this.trySelectCard(card_index);
            break;
          }
        }
      });
      const card_list_bounds = [];
      stage.addChildBefore($hand_card_list, $auto_btm_list);
      //card_list是deep监测来进行渲染，所以任意的操作都会造成手牌重绘，所以必须使用WeakMap对象来避免创建与销毁的开销。
      const hand_card_list_cache = new PIXI.CardListCache();
      unwatchers[unwatchers.length] = this.$watch(
        "card_list",
        card_list => {
          while ($hand_card_list.children.length) {
            $hand_card_list.removeChildAt(0);
          }
          card_list_bounds.length = 0;
          card_list.forEach((card, card_index) => {
            const $card = hand_card_list_cache.get(card, resources);
            $card.maxWidthHeight(
              width * 0.15,
              height * 0.2,
              () => {
                // use maxwidth
                $card.x = card_index * width * 0.07;
              },
              () => {
                // use maxheight
                $card.x = card_index * width * 0.05;
              }
            );
            $hand_card_list.addChild($card);
            $card.tint = card.is_used ? 0x999999 : 0xffffff;
            $card.y = card.is_selected ? $card.height * -0.2 : 0;
            if (!$card.__is_inited_bind_tap) {
              $card.__is_inited_bind_tap = true;
              $card.interactive = true;
              $card.buttonMode = true;
              $card.on("pointerdown", () => {
                this.startSelectCard(card, card_index);
              });
              // $card.on("pointermove", (e) => {
              //   if (e.target === e.currentTarget) {
              //     this.trySelectCard(card_index)
              //   }
              // });
              $card.on("pointerup", () => {
                this.endSelectCard();
              });
            }
          });
          if ($hand_card_list.children.length) {
            const card_height = $hand_card_list.children[0].height;
            $hand_card_list.y =
              height - card_height - $auto_btm_list.height * 0.9;
            $hand_card_list.x = width / 2 - $hand_card_list.width / 2;
          }
          // 获取所有牌的坐标
          $hand_card_list.children.forEach(($card, card_index) => {
            card_list_bounds.push({
              bounds: $card.getBounds(),
              card_index
            });
          });
          hand_card_list_bounds = $hand_card_list.getBounds();
        },
        {
          immediate: true,
          deep: true
        }
      );
    };
  },
  methods: {
    roomStatusToString,
    playerStatusToString,
    cartNameToHtml(card) {
      const card_info = card.split("_");
      const [type, num] = card_info;
      const symbol_map = {
        黑桃: "♠",
        方块: "♦",
        红心: "♥",
        梅花: "♣"
      };
      const color_map = {
        黑桃: "#000",
        方块: "#e30",
        红心: "#F00",
        梅花: "#333"
      };
      return `<div class='img' style="color:${color_map[type]};">
        <div class='symbol'>${symbol_map[type]}</div>
        <div class='number'>${num}</div>
      </div>`;
    },
    addSelectedCardsToRes(res_type, limit_num = 5) {
      const selected_cards = this.card_list.filter(card => card.is_selected);
      if (selected_cards.length === limit_num) {
        if (this[res_type].length) {
          this[res_type].forEach(card => {
            card.is_selected = true;
            card.is_used = false;
          });
        }
        this[res_type] = selected_cards;
        selected_cards.forEach(card => {
          card.is_selected = false;
          card.is_used = true;
        });
        // 自动填充最后的牌组
        const rest_card_list = this.card_list.filter(card => !card.is_used);
        if (rest_card_list.length === 5 || rest_card_list.length === 3) {
          const key = ["top", "mid", "btm"].find(
            key => this[key + "_card_list"].length === 0
          );
          if (!key) {
            return;
          }
          rest_card_list.forEach(card => card.is_selected = true);
          this.addSelectedCardsToRes(key + "_card_list", rest_card_list.length);
        }
      }
    },
    removeFromResCards(res_type) {
      const res_cards = this[res_type];
      res_cards.forEach(card => {
        card.is_used = false;
        card.is_selected = true;
      });
      this[res_type] = [];
    },
    selectCard(card_item, v = !card_item.is_selected) {
      if (!card_item.is_used) {
        card_item.is_selected = v;
      }
    },
    startSelectCard(card_item, card_index) {
      this.mul_select_from = card_index;
      this.selectCard(card_item);
      this.mul_select_val = card_item.is_used ? null : card_item.is_selected;
      this.mul_select_old_vals = this.card_list.map(card => card.is_selected);
    },
    trySelectCard(card_index) {
      if (this.mul_select_from !== null) {
        this.mul_select_to = card_index;
        const slice_from = Math.min(this.mul_select_from, this.mul_select_to);
        const slice_to = Math.max(this.mul_select_from, this.mul_select_to);
        this.card_list.forEach((card, i) => {
          if (i >= slice_from && i <= slice_to) {
            if (this.mul_select_val === null && !card.is_used) {
              this.mul_select_val = !card.is_selected;
            }
            this.selectCard(card, this.mul_select_val);
          } else {
            this.selectCard(card, this.mul_select_old_vals[i]);
          }
        });
      }
    },
    endSelectCard() {
      this.mul_select_from = null;
      this.mul_select_to = null;
      this.mul_select_val = null;
      this.mul_select_old_vals = null;
    },

    submitResWithSpecial() {
      const special_info = this.special_info;
      if (special_info && special_info.type) {
        if (special_info.combination && special_info.combination.length) {
          const combination = special_info.combination[0];
          ["top", "mid", "btm"].forEach(type => {
            this[`${type}_card_list`] = combination[type].map(card_txt => {
              const card = Card.getIns(card_txt);
              card.is_used = true;
              return card;
            });
          });
          const top_card_list = this.top_card_list;
          const mid_card_list = this.mid_card_list;
          const btm_card_list = this.btm_card_list;
          socket.emit("submit-res", {
            type: special_info.type,
            top: top_card_list,
            mid: mid_card_list,
            btm: btm_card_list
          });
        } else {
          socket.emit("submit-res", {
            type: special_info.type,
            all: this.card_list
          });
        }
      }
    },
    submitRes() {
      const top_card_list = this.top_card_list;
      const mid_card_list = this.mid_card_list;
      const btm_card_list = this.btm_card_list;
      socket.emit("submit-res", {
        top: top_card_list,
        mid: mid_card_list,
        btm: btm_card_list
      });
    },
    submitChangedCardList() {
      const selected_card_list = CARD_LIST.filter(card => card.is_selected);
      if (selected_card_list.length !== 13) {
        alert(`选中了${selected_card_list.length}张，必须选13张`);
        return;
      }
      CARD_LIST.forEach(card => {
        card.reset();
      });
      socket.emit("--changed-card-list--", selected_card_list);
    }
  }
});
